namespace SubSonic
{
    using SubSonic.Sugar;
    using SubSonic.Utilities;
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Text;
    using System.Web.UI;
    using System.Web.UI.HtmlControls;
    using System.Web.UI.WebControls;

    [DefaultProperty("TableName"), ToolboxData("<{0}:QuickTable runat=server></{0}:QuickTable>")]
    public class QuickTable : WebControl, INamingContainer
    {
        private readonly Button btnFirst = new Button();
        private readonly Button btnLast = new Button();
        private readonly Button btnNext = new Button();
        private readonly Button btnPrev = new Button();
        private string buttonFirstText = " << ";
        private string buttonLastText = " >> ";
        private string buttonNextText = " > ";
        private string buttonPreviousText = " < ";
        private readonly ArrayList colList = new ArrayList();
        private string columnList = string.Empty;
        private DataTable dataSource;
        private readonly DropDownList ddlPages = new DropDownList();
        private string headerLinkCSSClass = string.Empty;
        private readonly string headerLinkStyle = "text-decoration:none;color:black;font-size:12pt;font-family:arial;";
        private readonly Label lblRecordCount = new Label();
        private string linkOnColumn = string.Empty;
        private string linkToPage = string.Empty;
        private readonly Literal litPagerLabel = new Literal();
        private int pageIndex = 1;
        private string pagerButtonCSS = string.Empty;
        private readonly string pagerButtonStyle = "border:1px solid #cccccc;background-color:whitesmoke;font-family:helvetica;font-size:10pt";
        private string pagerCSS = string.Empty;
        private readonly string pagerStyle = "alignment:center; font-size:10pt;font-family:arial;border-top:1px solid #666666;margin-top:5px";
        private int pageSize;
        private string providerName = string.Empty;
        private TableSchema.Table schema;
        private bool showSort = true;
        private const string SORT_BY = "sortBy";
        private string sortBy;
        private string sortDirection = "ASC";
        private string tableAlternatingCSSClass = string.Empty;
        private readonly string tableAlternatingStyle = "padding:3px;background-color:whitesmoke;font-family:arial;font-size:10pt;";
        private string tableCellCSSClass = string.Empty;
        private readonly string tableCellStyle = "padding:3px;background-color:white;font-family:arial;font-size:10pt;";
        private string tableCSSClass = string.Empty;
        private string tableHeaderCSSClass = string.Empty;
        private readonly string tableHeaderStyle = "font-weight:bold; text-align:center;font-family:arial;font-size:12pt;border-bottom:1px solid #666666;";
        private string tableName = string.Empty;
        private readonly string tableStyle = string.Empty;
        private readonly HtmlTable tbl = new HtmlTable();
        private readonly HtmlTable tblPage = new HtmlTable();
        private readonly HtmlTable tblWrap = new HtmlTable();
        private HtmlTableCell td;
        private readonly HtmlTableCell tdBottom = new HtmlTableCell();
        private readonly HtmlTableCell tdTop = new HtmlTableCell();
        private const string TOTAL_RECORDS = "totalRecords";
        private int totalPages;
        private int totalRecords;
        private HtmlTableRow tr;
        private readonly HtmlTableRow trBottom = new HtmlTableRow();
        private readonly HtmlTableRow trTop = new HtmlTableRow();
        private List<Where> whereCollection;
        private string whereExpression = string.Empty;

        private void AddHeaderText(TableSchema.TableColumn col, HtmlTableCell tdHeaderCell, string overrideText)
        {
            if (this.showSort)
            {
                LinkButton child = new LinkButton();
                child.ID = "btn" + col.ColumnName;
                child.CommandArgument = col.ColumnName;
                child.Text = string.IsNullOrEmpty(overrideText) ? col.DisplayName : overrideText;
                if (!string.IsNullOrEmpty(this.headerLinkCSSClass))
                {
                    child.CssClass = this.headerLinkCSSClass;
                }
                else
                {
                    child.Attributes.Add("style", this.headerLinkStyle);
                }
                tdHeaderCell.Controls.Add(child);
                if (col.IsNumeric)
                {
                    tdHeaderCell.Align = "right";
                }
                else if (col.IsDateTime)
                {
                    tdHeaderCell.Align = "center";
                }
                child.Click += new EventHandler(this.Sort_Click);
            }
            else
            {
                tdHeaderCell.InnerHtml = string.IsNullOrEmpty(overrideText) ? overrideText : col.DisplayName;
            }
        }

        private void BuildHeader()
        {
            this.tr = new HtmlTableRow();
            string[] strArray = this.columnList.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            if (strArray.Length != 0)
            {
                foreach (string str in strArray)
                {
                    this.td = new HtmlTableCell();
                    if (!string.IsNullOrEmpty(this.tableHeaderCSSClass))
                    {
                        this.td.Attributes.Add("class", this.tableHeaderCSSClass);
                    }
                    else
                    {
                        this.td.Attributes.Add("style", this.tableHeaderStyle);
                    }
                    if (str.Contains(":"))
                    {
                        string[] strArray2 = str.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                        try
                        {
                            TableSchema.TableColumn column = this.schema.GetColumn(strArray2[0].Trim());
                            if (column == null)
                            {
                                column = this.schema.GetColumn(strArray2[1].Trim());
                            }
                            if (column == null)
                            {
                                throw new Exception("Can't find a column for this table named " + strArray2[0] + " or " + strArray2[1]);
                            }
                            this.colList.Add(column.ColumnName.ToLower());
                            this.AddHeaderText(column, this.td, strArray2[1]);
                            goto Label_018A;
                        }
                        catch
                        {
                            throw new Exception("Invalid Custom Columns. If you want to pass in a custom colum, it should be in the form 'columnName:Replacement Name'");
                        }
                    }
                    TableSchema.TableColumn col = this.schema.GetColumn(str.Trim());
                    if (col == null)
                    {
                        throw new Exception("Can't find a column for this table named " + str);
                    }
                    this.colList.Add(col.ColumnName.ToLower());
                    this.AddHeaderText(col, this.td, "");
                Label_018A:
                    this.tr.Cells.Add(this.td);
                }
            }
            else
            {
                foreach (TableSchema.TableColumn column3 in this.schema.Columns)
                {
                    this.td = new HtmlTableCell();
                    this.td.Attributes.Add("style", this.tableHeaderStyle);
                    this.AddHeaderText(column3, this.td, "");
                    this.tr.Cells.Add(this.td);
                    this.colList.Add(column3.ColumnName.ToLower());
                }
            }
            this.tbl.Rows.Add(this.tr);
        }

        private void BuildPager()
        {
            if (this.pageSize > 0)
            {
                HtmlTableRow row = new HtmlTableRow();
                this.tblPage.Rows.Add(row);
                HtmlTableCell cell = new HtmlTableCell();
                row.Cells.Add(cell);
                this.litPagerLabel.Text = " Page ";
                cell.Controls.Add(this.btnFirst);
                cell.Controls.Add(this.btnPrev);
                cell.Controls.Add(this.litPagerLabel);
                cell.Controls.Add(this.ddlPages);
                cell.Controls.Add(this.lblRecordCount);
                cell.Controls.Add(this.btnNext);
                cell.Controls.Add(this.btnLast);
                this.btnFirst.Text = this.buttonFirstText;
                this.btnLast.Text = this.buttonLastText;
                this.btnPrev.Text = this.buttonPreviousText;
                this.btnNext.Text = this.buttonNextText;
                this.btnFirst.CommandArgument = "1";
                this.btnFirst.Click += new EventHandler(this.Paging_Click);
                this.btnLast.Click += new EventHandler(this.Paging_Click);
                this.btnPrev.Click += new EventHandler(this.Paging_Click);
                this.btnNext.Click += new EventHandler(this.Paging_Click);
                this.ddlPages.SelectedIndexChanged += new EventHandler(this.ddlPages_SelectedIndexChanged);
                this.ddlPages.AutoPostBack = true;
                cell.ColSpan = this.colList.Count;
                cell.Align = "center";
                if (!string.IsNullOrEmpty(this.pagerCSS))
                {
                    cell.Attributes.Add("class", this.pagerCSS);
                }
                else
                {
                    cell.Attributes.Add("style", this.pagerStyle);
                }
                this.tblPage.Rows.Add(row);
            }
        }

        private void BuildRows()
        {
            for (int i = this.tbl.Rows.Count - 1; i > 0; i--)
            {
                this.tbl.Rows.RemoveAt(i);
            }
            string key = string.IsNullOrEmpty(this.tableCellCSSClass) ? "style" : "class";
            string str2 = string.IsNullOrEmpty(this.tableCellCSSClass) ? this.tableCellStyle : this.tableCellCSSClass;
            string str3 = string.IsNullOrEmpty(this.tableCellCSSClass) ? this.tableAlternatingStyle : this.tableAlternatingCSSClass;
            int count = this.dataSource.Rows.Count;
            for (int j = 0; j < count; j++)
            {
                DataRow row = this.dataSource.Rows[j];
                this.tr = new HtmlTableRow();
                if (Numbers.IsEven(j))
                {
                    this.tr.Attributes.Add(key, str2);
                }
                else
                {
                    this.tr.Attributes.Add(key, str3);
                }
                int num4 = 0;
                for (int k = 0; k < this.colList.Count; k++)
                {
                    string columnName = this.colList[k].ToString();
                    TableSchema.TableColumn column = this.schema.GetColumn(columnName);
                    this.td = new HtmlTableCell();
                    if (column.IsDateTime)
                    {
                        DateTime time;
                        if (DateTime.TryParse(row[columnName].ToString(), out time))
                        {
                            this.td.InnerHtml = time.ToShortDateString();
                        }
                        else
                        {
                            this.td.InnerHtml = row[columnName].ToString();
                        }
                        this.td.Align = "center";
                    }
                    else if (column.DataType == DbType.Currency)
                    {
                        decimal num6;
                        decimal.TryParse(row[columnName].ToString(), out num6);
                        this.td.InnerHtml = num6.ToString("c");
                        this.td.Align = "right";
                    }
                    else if (column.IsNumeric)
                    {
                        this.td.InnerHtml = row[columnName].ToString();
                        this.td.Align = "right";
                    }
                    else
                    {
                        this.td.InnerHtml = row[columnName].ToString();
                    }
                    if (!string.IsNullOrEmpty(this.linkToPage))
                    {
                        string str5;
                        if (this.schema.PrimaryKey != null)
                        {
                            str5 = string.Concat(new object[] { "<a href=\"", this.linkToPage, "?id=", row[this.schema.PrimaryKey.ColumnName], "\">", this.td.InnerHtml, "</a>" });
                        }
                        else
                        {
                            str5 = "<a href=\"" + this.linkToPage + "\">" + this.td.InnerHtml + "</a>";
                        }
                        if ((!string.IsNullOrEmpty(this.linkOnColumn) && Utility.IsMatch(this.linkOnColumn, columnName)) || (num4 == 0))
                        {
                            this.td.InnerHtml = str5;
                        }
                    }
                    this.tr.Cells.Add(this.td);
                    num4++;
                }
                this.tbl.Rows.Add(this.tr);
            }
        }

        protected override void CreateChildControls()
        {
            base.CreateChildControls();
            this.tbl.CellPadding = 3;
            this.tbl.CellSpacing = 0;
            this.tbl.Width = "100%";
            this.tblPage.Width = "100%";
            this.trTop.Cells.Add(this.tdTop);
            this.tblWrap.Rows.Add(this.trTop);
            this.trBottom.Cells.Add(this.tdBottom);
            this.tblWrap.Rows.Add(this.trBottom);
            this.tdTop.Controls.Add(this.tbl);
            this.tdBottom.Controls.Add(this.tblPage);
            this.Controls.Add(this.tblWrap);
            if (!string.IsNullOrEmpty(this.tableCSSClass))
            {
                this.tbl.Attributes.Add("class", this.tableCSSClass);
            }
            else
            {
                this.tbl.Attributes.Add("style", this.tableStyle);
            }
            if (!string.IsNullOrEmpty(this.pagerButtonCSS))
            {
                this.btnFirst.Attributes.Add("class", this.pagerButtonCSS);
                this.btnPrev.Attributes.Add("class", this.pagerButtonCSS);
                this.btnNext.Attributes.Add("class", this.pagerButtonCSS);
                this.btnLast.Attributes.Add("class", this.pagerButtonCSS);
                this.ddlPages.Attributes.Add("class", this.pagerButtonCSS);
            }
            else
            {
                this.btnFirst.Attributes.Add("style", this.pagerButtonStyle);
                this.btnPrev.Attributes.Add("style", this.pagerButtonStyle);
                this.btnNext.Attributes.Add("style", this.pagerButtonStyle);
                this.btnLast.Attributes.Add("style", this.pagerButtonStyle);
                this.ddlPages.Attributes.Add("style", this.pagerButtonStyle);
            }
            this.schema = DataService.GetSchema(this.tableName, this.ProviderName, TableType.Table);
            if (this.schema == null)
            {
                this.schema = DataService.GetSchema(this.tableName, this.ProviderName, TableType.View);
            }
            if (this.schema == null)
            {
                throw new Exception("Can't find a table names " + this.tableName + "; did you set the correct providerName?");
            }
            this.BuildHeader();
            this.BuildPager();
            this.LoadGrid();
            this.trBottom.Visible = this.pageSize < this.totalRecords;
        }

        private void ddlPages_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.pageIndex = int.Parse(this.ddlPages.SelectedValue);
            this.ViewState["currentPage"] = this.pageIndex;
            this.LoadGrid();
        }

        private void DecideSortDirection()
        {
            if (this.ViewState["sortBy"] != null)
            {
                string str = this.ViewState["sortBy"].ToString();
                if (string.IsNullOrEmpty(this.SortBy))
                {
                    this.SortBy = str;
                }
                else if (str == this.SortBy)
                {
                    this.SortDirection = " DESC";
                    this.ViewState["sortBy"] = null;
                }
                else
                {
                    this.ViewState["sortBy"] = this.SortBy;
                }
            }
            else
            {
                this.ViewState["sortBy"] = this.SortBy;
            }
        }

        private void EnsureTotals(Query qry)
        {
            if (this.pageSize > 0)
            {
                if (this.ViewState["totalRecords"] == null)
                {
                    this.TotalRecords = qry.GetRecordCount();
                    this.ViewState["totalRecords"] = this.TotalRecords;
                }
                else
                {
                    this.TotalRecords = (int) this.ViewState["totalRecords"];
                }
                this.totalPages = (this.totalRecords / this.pageSize) + 1;
                this.lblRecordCount.Text = string.Concat(new object[] { " of ", this.totalPages, " (", this.totalRecords, " total) " });
                if (this.ddlPages.Items.Count == 0)
                {
                    for (int i = 1; i <= this.totalPages; i++)
                    {
                        this.ddlPages.Items.Add(new ListItem(i.ToString(), i.ToString()));
                    }
                }
            }
        }

        private void LoadGrid()
        {
            this.DecideSortDirection();
            if (string.IsNullOrEmpty(this.tableName))
            {
                throw new Exception("No tableName property set - please be sure to set the name of the table or view you'd like to see");
            }
            Query qry = new Query(this.tableName, this.ProviderName);
            StringBuilder builder = new StringBuilder("*");
            if (!string.IsNullOrEmpty(this.columnList))
            {
                builder = new StringBuilder();
                for (int i = 0; i < this.colList.Count; i++)
                {
                    builder.Append(this.colList[i]);
                    if ((i + 1) < this.colList.Count)
                    {
                        builder.Append(", ");
                    }
                }
            }
            qry.SelectList = builder.ToString();
            if (!string.IsNullOrEmpty(this.sortBy))
            {
                TableSchema.TableColumn column = qry.Schema.GetColumn(this.sortBy);
                if (((column != null) && (column.MaxLength < 0x800)) && ((column.DataType != DbType.Binary) && (column.DataType != DbType.Byte)))
                {
                    if (string.IsNullOrEmpty(this.sortDirection) || (this.sortDirection.Trim() == "ASC"))
                    {
                        qry.OrderBy = OrderBy.Asc(this.sortBy);
                    }
                    else
                    {
                        qry.OrderBy = OrderBy.Desc(this.sortBy);
                    }
                }
            }
            if (this.pageSize > 0)
            {
                qry.PageSize = this.pageSize;
                qry.PageIndex = this.pageIndex;
                this.ddlPages.SelectedValue = this.pageIndex.ToString();
            }
            qry.CheckLogicalDelete();
            if (!string.IsNullOrEmpty(this.whereExpression))
            {
                qry.WHERE(this.whereExpression);
            }
            if (this.whereCollection != null)
            {
                qry.wheres = this.whereCollection;
            }
            DataSet set = qry.ExecuteDataSet();
            if (set.Tables.Count <= 0)
            {
                throw new Exception("Bad query - no data returned. Did you set the correct provider?");
            }
            this.dataSource = set.Tables[0];
            this.EnsureTotals(qry);
            this.SetPagingButtonState();
            this.BuildRows();
        }

        private void Paging_Click(object sender, EventArgs e)
        {
            int num;
            Button button = (Button) sender;
            int.TryParse(button.CommandArgument, out num);
            this.PageIndex = num;
            this.ViewState["currentPage"] = num;
            this.LoadGrid();
        }

        private void SetPagingButtonState()
        {
            if (this.ViewState["currentPage"] != null)
            {
                this.pageIndex = (int) this.ViewState["currentPage"];
            }
            else
            {
                this.pageIndex = 1;
                this.ViewState["currentPage"] = 1;
            }
            if ((this.totalPages > 0) && (this.totalRecords > 0))
            {
                if (this.pageIndex == 0)
                {
                    this.pageIndex = 1;
                }
                int num = this.pageIndex + 1;
                int num2 = this.pageIndex - 1;
                this.btnNext.CommandArgument = num.ToString();
                this.btnPrev.CommandArgument = num2.ToString();
                this.btnLast.CommandArgument = this.totalPages.ToString();
                this.btnPrev.Enabled = true;
                this.btnNext.Enabled = true;
                this.btnLast.Enabled = true;
                this.btnFirst.Enabled = true;
                if (this.pageIndex == this.totalPages)
                {
                    this.btnNext.Enabled = false;
                    this.btnLast.Enabled = false;
                }
                else if (this.pageIndex == 1)
                {
                    this.btnPrev.Enabled = false;
                    this.btnFirst.Enabled = false;
                }
            }
        }

        private void Sort_Click(object sender, EventArgs e)
        {
            LinkButton button = (LinkButton) sender;
            this.SortBy = button.CommandArgument;
            this.LoadGrid();
        }

        public string ButtonFirstText
        {
            get
            {
                return this.buttonFirstText;
            }
            set
            {
                this.buttonFirstText = value;
            }
        }

        public string ButtonLastText
        {
            get
            {
                return this.buttonLastText;
            }
            set
            {
                this.buttonLastText = value;
            }
        }

        public string ButtonNextText
        {
            get
            {
                return this.buttonNextText;
            }
            set
            {
                this.buttonNextText = value;
            }
        }

        public string ButtonPreviousText
        {
            get
            {
                return this.buttonPreviousText;
            }
            set
            {
                this.buttonPreviousText = value;
            }
        }

        public string ColumnList
        {
            get
            {
                return this.columnList;
            }
            set
            {
                this.columnList = value;
            }
        }

        public string HeaderLinkCSSClass
        {
            get
            {
                return this.headerLinkCSSClass;
            }
            set
            {
                this.headerLinkCSSClass = value;
            }
        }

        public string LinkOnColumn
        {
            get
            {
                return this.linkOnColumn;
            }
            set
            {
                this.linkOnColumn = value;
            }
        }

        public string LinkToPage
        {
            get
            {
                return this.linkToPage;
            }
            set
            {
                this.linkToPage = value;
            }
        }

        public string PageButtonCSSClass
        {
            get
            {
                return this.pagerButtonCSS;
            }
            set
            {
                this.pagerButtonCSS = value;
            }
        }

        public int PageIndex
        {
            get
            {
                return this.pageIndex;
            }
            set
            {
                this.pageIndex = value;
            }
        }

        public string PagerCSS
        {
            get
            {
                return this.pagerCSS;
            }
            set
            {
                this.pagerCSS = value;
            }
        }

        public int PageSize
        {
            get
            {
                return this.pageSize;
            }
            set
            {
                this.pageSize = value;
            }
        }

        public string ProviderName
        {
            get
            {
                if (string.IsNullOrEmpty(this.providerName))
                {
                    this.providerName = DataService.Provider.Name;
                }
                return this.providerName;
            }
            set
            {
                this.providerName = value;
            }
        }

        public bool ShowSort
        {
            get
            {
                return this.showSort;
            }
            set
            {
                this.showSort = value;
            }
        }

        public string SortBy
        {
            get
            {
                return this.sortBy;
            }
            set
            {
                this.sortBy = value;
            }
        }

        public string SortDirection
        {
            get
            {
                return this.sortDirection;
            }
            set
            {
                this.sortDirection = value;
            }
        }

        public string TableAlternatingCSSClass
        {
            get
            {
                return this.tableAlternatingCSSClass;
            }
            set
            {
                this.tableAlternatingCSSClass = value;
            }
        }

        public string TableCellCSSClass
        {
            get
            {
                return this.tableCellCSSClass;
            }
            set
            {
                this.tableCellCSSClass = value;
            }
        }

        public string TableCSSClass
        {
            get
            {
                return this.tableCSSClass;
            }
            set
            {
                this.tableCSSClass = value;
            }
        }

        public string TableHeaderCSSClass
        {
            get
            {
                return this.tableHeaderCSSClass;
            }
            set
            {
                this.tableHeaderCSSClass = value;
            }
        }

        public string TableName
        {
            get
            {
                return this.tableName;
            }
            set
            {
                this.tableName = value;
            }
        }

        public int TotalPages
        {
            get
            {
                return this.totalPages;
            }
            set
            {
                this.totalPages = value;
            }
        }

        public int TotalRecords
        {
            get
            {
                return this.totalRecords;
            }
            set
            {
                this.totalRecords = value;
            }
        }

        public List<Where> WhereCollection
        {
            get
            {
                return this.whereCollection;
            }
            set
            {
                this.whereCollection = value;
            }
        }

        public string WhereExpression
        {
            get
            {
                return this.whereExpression;
            }
            set
            {
                this.whereExpression = value;
            }
        }
    }
}

